package com.adk.backend.controller;

import com.adk.backend.annotation.RequiresPermission;
import com.adk.backend.common.Result;
import com.adk.backend.entity.LxFinanceCheckDetails;
import com.adk.backend.mapper.CostMapper;
import com.adk.backend.service.CostService;
import com.adk.backend.util.JwtUtil;
import com.adk.backend.util.LogUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 成本管理控制器
 */
@Slf4j
@RestController
@RequestMapping("/api/cost")
public class CostController {
    
    @Autowired
    private CostService costService;
    
    @Autowired
    private CostMapper costMapper;
    
    @Autowired
    private LogUtil logUtil;
    
    @Autowired
    private JwtUtil jwtUtil;
    
    /**
     * 查询Cou成本列表（空运成本）
     */
    @RequiresPermission("view")
    @GetMapping("/cou")
    public Result<List<Map<String, Object>>> getCouCostList(
            @RequestParam(required = false) Long monthId) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("monthId", monthId);
            List<Map<String, Object>> list = costService.getCouCostList(params);
            return Result.success(list);
        } catch (Exception e) {
            log.error("查询Cou成本列表失败", e);
            return Result.error("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 查询Cargo成本列表（空运货物成本）
     */
    @RequiresPermission("view")
    @GetMapping("/cargo")
    public Result<List<Map<String, Object>>> getCargoCostList(
            @RequestParam(required = false) Long monthId) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("monthId", monthId);
            List<Map<String, Object>> list = costService.getCargoCostList(params);
            return Result.success(list);
        } catch (Exception e) {
            log.error("查询Cargo成本列表失败", e);
            return Result.error("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 查询海运成本列表
     */
    @RequiresPermission("view")
    @GetMapping("/sea")
    public Result<List<Map<String, Object>>> getSeaCostList(
            @RequestParam(required = false) Long monthId) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("monthId", monthId);
            List<Map<String, Object>> list = costService.getSeaCostList(params);
            return Result.success(list);
        } catch (Exception e) {
            log.error("查询海运成本列表失败", e);
            return Result.error("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 获取财务对账月份列表
     */
    @RequiresPermission("view")
    @GetMapping("/month/list")
    public Result<List<Map<String, Object>>> getFinanceCheckMonthList() {
        try {
            List<Map<String, Object>> list = costService.getFinanceCheckMonthList();
            return Result.success(list);
        } catch (Exception e) {
            log.error("查询财务对账月份列表失败", e);
            return Result.error("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 根据提单ID查询财务对账明细
     */
    @RequiresPermission("view")
    @GetMapping("/details")
    public Result<Map<String, Object>> getFinanceCheckDetails(@RequestParam Long blId) {
        try {
            Map<String, Object> details = costService.getFinanceCheckDetailsByBlId(blId);
            return Result.success(details);
        } catch (Exception e) {
            log.error("查询财务对账明细失败", e);
            return Result.error("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 计算合计金额
     */
    @RequiresPermission("view")
    @PostMapping("/total-amount")
    public Result<Map<String, Object>> calculateTotalAmount(@RequestBody Map<String, Object> params) {
        try {
            @SuppressWarnings("unchecked")
            List<Long> blIds = (List<Long>) params.get("blIds");
            Map<String, Object> result = costService.calculateTotalAmount(blIds);
            return Result.success(result);
        } catch (Exception e) {
            log.error("计算合计金额失败", e);
            return Result.error("计算失败：" + e.getMessage());
        }
    }
    
    /**
     * 设置提单的财务对账月份
     */
    @RequiresPermission("edit")
    @PostMapping("/set-month")
    public Result<Boolean> setBlFinanceCheckMonth(
            @RequestParam Long blId,
            @RequestParam Long monthId,
            @RequestParam(required = false) Long oldMonthId,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            // 如果没有提供oldMonthId，先查询
            if (oldMonthId == null) {
                Map<String, Object> blInfo = costMapper.selectBlFinanceCheck(blId);
                if (blInfo != null && blInfo.get("f_check") != null) {
                    oldMonthId = ((Number) blInfo.get("f_check")).longValue();
                }
            }
            boolean success = costService.setBlFinanceCheckMonth(blId, monthId, oldMonthId);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "bl_list", blId, "设置财务对账月份", request);
                return Result.success("设置成功", true);
            }
            return Result.error("设置失败");
        } catch (Exception e) {
            log.error("设置财务对账月份失败", e);
            return Result.error("设置失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新中港费用
     */
    @RequiresPermission("edit")
    @PostMapping("/zg-fee")
    public Result<Boolean> saveZgFee(
            @RequestBody LxFinanceCheckDetails details,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            // 计算逻辑在Service中处理
            boolean success = costService.saveZgFee(details);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", details.getId(), "保存中港费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存中港费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新头程费用
     */
    @RequiresPermission("edit")
    @PostMapping("/tx-fee")
    public Result<Boolean> saveTxFee(
            @RequestBody LxFinanceCheckDetails details,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            // 计算逻辑在Service中处理
            boolean success = costService.saveTxFee(details);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", details.getId(), "保存头程费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存头程费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新报关费用
     */
    @RequiresPermission("edit")
    @PostMapping("/declare-fee")
    public Result<Boolean> saveDeclareFee(
            @RequestBody LxFinanceCheckDetails details,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            // 计算逻辑在Service中处理（根据qghId判断DB类型或非DB类型）
            boolean success = costService.saveDeclareFee(details);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", details.getId(), "保存报关费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存报关费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新证书费用
     */
    @RequiresPermission("edit")
    @PostMapping("/cert-fee")
    public Result<Boolean> saveCertFee(
            @RequestBody LxFinanceCheckDetails details,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            // 计算逻辑在Service中处理
            boolean success = costService.saveCertFee(details);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", details.getId(), "保存证书费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存证书费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新派送费用
     */
    @RequiresPermission("edit")
    @PostMapping("/ps-fee")
    public Result<Boolean> savePsFee(
            @RequestBody LxFinanceCheckDetails details,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            // 计算逻辑在Service中处理
            boolean success = costService.savePsFee(details);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", details.getId(), "保存派送费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存派送费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新汇率
     */
    @RequiresPermission("edit")
    @PostMapping("/exchange-rate")
    public Result<Boolean> saveExchangeRate(
            @RequestParam Long blId,
            @RequestParam(required = false) Long fcdId,
            @RequestParam BigDecimal newRate,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            boolean success = costService.saveExchangeRate(blId, fcdId, newRate);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", fcdId, "保存汇率", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存汇率失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新货拉拉费用
     */
    @RequiresPermission("edit")
    @PostMapping("/hll-fee")
    public Result<Boolean> saveHllFee(
            @RequestParam Long blId,
            @RequestParam(required = false) Long fcdId,
            @RequestParam BigDecimal hllFee,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            boolean success = costService.saveHllFee(blId, fcdId, hllFee);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", fcdId, "保存货拉拉费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存货拉拉费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新VAT费用
     */
    @RequiresPermission("edit")
    @PostMapping("/vat-fee")
    public Result<Boolean> saveVatFee(
            @RequestBody LxFinanceCheckDetails details,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            // VAT计算已在Service中处理
            boolean success = costService.saveVatFee(details);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", details.getId(), "保存VAT费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存VAT费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新GS费用
     */
    @RequiresPermission("edit")
    @PostMapping("/gs-fee")
    public Result<Boolean> saveGsFee(
            @RequestParam Long blId,
            @RequestParam(required = false) Long fcdId,
            @RequestParam BigDecimal gsFee,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            boolean success = costService.saveGsFee(blId, fcdId, gsFee);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", fcdId, "保存GS费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存GS费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新DD费用
     */
    @RequiresPermission("edit")
    @PostMapping("/dd-fee")
    public Result<Boolean> saveDdFee(
            @RequestParam Long blId,
            @RequestParam(required = false) Long fcdId,
            @RequestParam BigDecimal ddFee,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            boolean success = costService.saveDdFee(blId, fcdId, ddFee);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", fcdId, "保存DD费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存DD费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新QT费用
     */
    @RequiresPermission("edit")
    @PostMapping("/qt-fee")
    public Result<Boolean> saveQtFee(
            @RequestParam Long blId,
            @RequestParam(required = false) Long fcdId,
            @RequestParam BigDecimal qtFee,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            boolean success = costService.saveQtFee(blId, fcdId, qtFee);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", fcdId, "保存QT费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存QT费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新Cargo派送费用
     */
    @RequiresPermission("edit")
    @PostMapping("/cargo-ps-fee")
    public Result<Boolean> saveCargoPsFee(
            @RequestParam Long blId,
            @RequestParam(required = false) Long fcdId,
            @RequestParam BigDecimal newPsFee,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            boolean success = costService.saveCargoPsFee(blId, fcdId, newPsFee);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", fcdId, "保存Cargo派送费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存Cargo派送费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新收货人费用
     */
    @RequiresPermission("edit")
    @PostMapping("/cnee-fee")
    public Result<Boolean> saveCneeFee(
            @RequestParam Long blId,
            @RequestParam(required = false) Long fcdId,
            @RequestParam BigDecimal cnee,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            boolean success = costService.saveCneeFee(blId, fcdId, cnee);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", fcdId, "保存收货人费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存收货人费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 保存或更新Cargo报关费用
     */
    @RequiresPermission("edit")
    @PostMapping("/cargo-declare-fee")
    public Result<Boolean> saveCargoDeclareFee(
            @RequestBody LxFinanceCheckDetails details,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            // 计算总清关费用
            if (details.getCustomFee() != null && details.getJcFee() != null) {
                BigDecimal totalCustom = details.getCustomFee().add(details.getJcFee());
                details.setTotalCustom(totalCustom);
            }
            boolean success = costService.saveCargoDeclareFee(details);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check_details", details.getId(), "保存Cargo报关费用", request);
                return Result.success("保存成功", true);
            }
            return Result.error("保存失败");
        } catch (Exception e) {
            log.error("保存Cargo报关费用失败", e);
            return Result.error("保存失败：" + e.getMessage());
        }
    }
    
    /**
     * 更新财务对账月份汇率
     */
    @RequiresPermission("edit")
    @PostMapping("/month/exchange-rate")
    public Result<Boolean> updateFinanceCheckExchangeRate(
            @RequestParam Long monthId,
            @RequestParam BigDecimal exchangeRate,
            @RequestHeader(value = "Authorization", required = false) String token,
            HttpServletRequest request) {
        try {
            boolean success = costService.updateFinanceCheckExchangeRate(monthId, exchangeRate);
            if (success) {
                logUtil.logAction(getCurrentUserIdLong(token), null, "finance_check", monthId, "更新汇率", request);
                return Result.success("更新成功", true);
            }
            return Result.error("更新失败");
        } catch (Exception e) {
            log.error("更新财务对账月份汇率失败", e);
            return Result.error("更新失败：" + e.getMessage());
        }
    }
    
    /**
     * 获取QGH信息
     */
    @RequiresPermission("view")
    @GetMapping("/qgh/info")
    public Result<Map<String, Object>> getQghInfo(@RequestParam Long qghId) {
        try {
            Map<String, Object> info = costService.getQghInfo(qghId);
            return Result.success(info);
        } catch (Exception e) {
            log.error("查询QGH信息失败", e);
            return Result.error("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 获取QGH列表
     */
    @RequiresPermission("view")
    @GetMapping("/qgh/list")
    public Result<List<Map<String, Object>>> getQghList() {
        try {
            List<Map<String, Object>> list = costService.getQghList();
            return Result.success(list);
        } catch (Exception e) {
            log.error("查询QGH列表失败", e);
            return Result.error("查询失败：" + e.getMessage());
        }
    }
    
    /**
     * 获取派送费用订单列表
     */
    @RequiresPermission("view")
    @GetMapping("/ps-fee/order-list")
    public Result<List<Map<String, Object>>> getPsFeeOrderList(@RequestParam String blNo) {
        try {
            List<Map<String, Object>> list = costService.getPsFeeOrderList(blNo);
            return Result.success(list);
        } catch (Exception e) {
            log.error("获取派送费用订单列表失败", e);
            return Result.error("获取派送费用订单列表失败：" + e.getMessage());
        }
    }
    
    /**
     * 获取当前用户ID（从token中获取）
     */
    private Integer getCurrentUserId(String token) {
        if (token == null || token.isEmpty()) {
            return null;
        }
        try {
            String jwtToken = token.startsWith("Bearer ") ? token.substring(7) : token;
            Long userId = jwtUtil.getUserIdFromToken(jwtToken);
            return userId != null ? userId.intValue() : null;
        } catch (Exception e) {
            log.error("解析token失败", e);
            return null;
        }
    }
    
    private Long getCurrentUserIdLong(String token) {
        if (token == null || token.isEmpty()) {
            return null;
        }
        try {
            String jwtToken = token.startsWith("Bearer ") ? token.substring(7) : token;
            return jwtUtil.getUserIdFromToken(jwtToken);
        } catch (Exception e) {
            log.error("解析token失败", e);
            return null;
        }
    }
}

